package com.wjr.braveheart.utils;

import android.util.Log;

import com.wjr.braveheart.BuildConfig;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;


/**
 * Created by WeiJinRan on 2019/4/15.
 * Version:
 * Describe:Log日志打印工具（isJson可以使用其他Json jar包来判定）
 * PS: Be kind when you are born.
 * Not easy to write code, please indicate.
 */

public class LogUtils {
    /**
     * 点击跳转到类的关键字  eclipse是 at android studio是☞.(任意文字加.)
     */
    private static String methodNameLogo = "☺☺☺ ☞.  ";//☜☝☞☟♧♡☺☹┉╱〖«【《▓
    /**
     * logcat在实现上对于message的内存分配大概,2k左右, 所以超过的内容都直接被丢弃,设置文本长度超过LOG_MAX_LENGTH分多条打印
     */
    private final static int LOG_MAX_LENGTH = 2048;
    /**
     * Json缩进
     */
    private static final int JSON_INDENT = 4;

    static String className;//类名
    static String methodName;//方法名
    static int lineNumber;//行数

    /**
     * 判断是否可以调试
     *
     * @return
     */
    public static boolean isDebuggable() {
        return BuildConfig.DEBUG;
    }

    /**
     * 拼接方法名和所在类的行数
     *
     * @return
     */
    private static String createMethodNamesLog() {
        StringBuffer buffer = new StringBuffer();
        buffer.append(methodNameLogo);
        buffer.append(methodName);
        buffer.append("(").append(className).append(":").append(lineNumber).append("): ");
        return buffer.toString();
    }

    /**
     * 打印日志
     *
     * @param formatStr
     */
    private static void createLog(int type, String formatStr) {
        Log.println(type, className, createMethodNamesLog());
        Log.println(type, className, logContent(type, formatStr));
    }

    /**
     * 获取文件名、方法名、所在行数
     *
     * @param sElements
     */
    private static void getMethodNames(StackTraceElement[] sElements) {

        //我们的入口是L类的方法，所以，我们直接遍历，L类相关的下一个非L类的栈帧信息就是具体调用的方法。
        StackTraceElement targetStackTrace = null;
        boolean shouldTrace = false;
        for (StackTraceElement sElement : sElements) {
            boolean isLogMethod = sElement.getClassName().equals(LogUtils.class.getName());
            if (shouldTrace && !isLogMethod) {
                targetStackTrace = sElement;
                break;
            }
            shouldTrace = isLogMethod;
        }
        className = targetStackTrace.getFileName();
        methodName = targetStackTrace.getMethodName();
        lineNumber = targetStackTrace.getLineNumber();
    }

    public static void e(String message) {
        if (!isDebuggable())
            return;
        getMethodNames(new Throwable().getStackTrace());
        createLog(Log.ERROR, formatStr(message));
    }


    public static void i(String message) {
        if (!isDebuggable())
            return;
        getMethodNames(new Throwable().getStackTrace());
        createLog(Log.INFO, formatStr(message));
    }

    public static void d(String message) {
        if (!isDebuggable())
            return;
        getMethodNames(new Throwable().getStackTrace());
        createLog(Log.DEBUG, formatStr(message));
    }

    public static void v(String message) {
        if (!isDebuggable())
            return;
        getMethodNames(new Throwable().getStackTrace());
        createLog(Log.VERBOSE, formatStr(message));
    }

    public static void w(String message) {
        if (!isDebuggable())
            return;
        getMethodNames(new Throwable().getStackTrace());
        createLog(Log.WARN, formatStr(message));
    }

    /**
     * 识别数据类型
     *
     * @param message
     * @return
     */
    private static String formatStr(String message) {
        String formatStr = null;
        if (isJson(message)) {
            formatStr = formatJson(message);
        } else if (message instanceof String) {
            formatStr = message;
        }
        return formatStr;
    }

    /**
     * 是否为Json数据
     *
     * @param message
     * @return
     */
    public static boolean isJson(String message) {
        try {
            new JSONObject(message);
        } catch (JSONException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * json格式化
     *
     * @param jsonStr
     * @return
     */
    private static String formatJson(String jsonStr) {
        try {
            jsonStr = jsonStr.trim();
            if (jsonStr.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(jsonStr);
                return jsonObject.toString(JSON_INDENT);
            }
            if (jsonStr.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(jsonStr);
                return jsonArray.toString(JSON_INDENT);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "Json格式有误: " + jsonStr;
    }

    /**
     * 打印内容
     *
     * @param type
     * @param text
     * @return
     */
    private static String logContent(int type, String text) {
        if (text.length() < 50) {// 内容长度不超过50，前面加空格加到50
            int minLeng = 50 - text.length();
            // Log.i(logtag, "leng========" + leng + "   " + text.length());
            if (minLeng > 0) {
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < minLeng; i++) {
                    stringBuilder.append(" ");
                }
                text = text + stringBuilder.toString();
            }
        } else if (text.length() > LOG_MAX_LENGTH) {// 内容超过logcat单条打印上限，分批打印
            //Log.i(logtag, "text长度=========" + text.length());
            int logTime = text.length() / LOG_MAX_LENGTH;
            for (int i = 0; i < logTime; i++) {
                String leng = text.substring(i * LOG_MAX_LENGTH, (i + 1)
                        * LOG_MAX_LENGTH);
                // 提示
                if (i == 0) {
                    Log.println(type, className, "第一行 ☞:  " + leng);
                } else {
                    Log.println(type, className, "接上行 ☞:  " + leng);
                }

            }
            text = "接上行 ☞:  "
                    + text.substring(logTime * LOG_MAX_LENGTH, text.length());
        }
        return text;
    }
}
